package com.example.myblogserver.controller.tourist;

import com.example.myblogserver.common.result.Result;
import com.example.myblogserver.common.utils.RedisUtil;
import com.example.myblogserver.dto.CommentDTO;
import com.example.myblogserver.dto.SendCodeDTO;
import com.example.myblogserver.model.Articles;
import com.example.myblogserver.model.Comments;
import com.example.myblogserver.service.ArticleService;
import com.example.myblogserver.service.CommentService;
import com.example.myblogserver.service.EmailService;
import com.example.myblogserver.vo.CategoryVO;
import com.example.myblogserver.vo.VisitorVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/tourist")
@Slf4j
@Api(tags = "游客相关接口")
public class TouristController {


    @Autowired
    private ArticleService articleService;
    @Autowired
    private CommentService commentService;
    @Autowired
    private EmailService emailService;
    @Autowired
    private RedisUtil redisUtil;


   /**
 * 获取分类文章列表
 * @param categoryId 可选分类ID
 * @param pageSize 分页大小
 * @param currentPage 当前页码
 * @return
 */
@GetMapping("/articles")
@ApiOperation(value = "获取分类文章列表（支持分页和分类筛选）")
public Result<Object> getArticlesByCategoryIdAndPage(
    @RequestParam(required = false) Long categoryId,
    @RequestParam(defaultValue = "10") Integer pageSize,
    @RequestParam(defaultValue = "1") Integer currentPage) {
    log.info("获取分类文章列表，分类ID：{}，分页大小：{}，当前页码：{}", categoryId, pageSize, currentPage);

    // 定义Redis缓存键
    String cacheKey = "article:list:" + categoryId + ":" + pageSize + ":" + currentPage;
    // 检查文章缓存
    Object cachedArticles = redisUtil.getArticle(cacheKey);
    if (cachedArticles != null) {
        log.info("从 Redis 缓存获取文章列表");
        return Result.success(cachedArticles);
    }
    // 如果缓存不存在，从数据库获取文章列表，（支持分页和分类筛选）
    List<Articles> articles = articleService.getArticlesByCategoryIdAndPage(categoryId, pageSize, currentPage);
    // 将文章数据写入 Redis 缓存，设置过期时间为 15 分钟
    redisUtil.setArticle(cacheKey, articles, 20);
    return Result.success(articles);
}


    /**
     * 获取文章详情
     * @param id
     * @return
     */
@GetMapping("/article/{id}")
@ApiOperation(value = "获取文章详情")
public Result<Object> getArticleById(@PathVariable Long id) {
    log.info("获取文章详情");

    String cacheKey = "article:detail:" + id;

    Object cachedArticle = redisUtil.getArticle(cacheKey);
    if (cachedArticle != null) {
        // 记录访客IP
        recordVisitorIp(id);
        return Result.success(cachedArticle);
    }

    Object article = articleService.getArticleById(id);
    redisUtil.setArticle(cacheKey, article,  15);
    // 记录访客IP
    recordVisitorIp(id);
    return Result.success(article);
}


    /**
     * 获取文章分类
     * @return
     */
    @GetMapping("/article/category")
    @ApiOperation(value = "获取文章分类")
    public Result<List<CategoryVO>> getArticleCategory() {
        log.info("获取文章分类");

        List<CategoryVO> categoryVOList = articleService.getArticleCategory();
        return Result.success(categoryVOList);
    }

    /**
     * 新增评论
     * @param commentDTO
     * @return
     */
    @PostMapping("/comment")
    @ApiOperation(value = "新增评论")
    public Result<Object> addComment(@RequestBody CommentDTO commentDTO) {
        log.info("新增评论");
        commentService.addComment(commentDTO);
        return Result.success();
    }

    /**
     * 获取文章评论
     * @param articleId
     * @return
     */
    @GetMapping("/comments/{articleId}")
    @ApiOperation(value = "获取文章评论")
    public Result<List<Comments>> getCommentsByArticleId(@PathVariable Long articleId) {
        log.info("获取文章评论");
        return Result.success(commentService.getCommentsByArticleId(articleId));
    }
    /**
     * 验证码获取
     * @param sendCodeDTO
     * @return
     */
    @PostMapping("/code")
    @ApiOperation(value = "验证码获取")
    public Result<Object> getCode(@RequestBody SendCodeDTO sendCodeDTO) {
        log.info("验证码获取");
        log.info("用户邮箱：{}", sendCodeDTO.getUserEmail());
        String code = generateVerificationCode(6);
        emailService.sendEmail(sendCodeDTO.getUserEmail(), code);
        // 保存验证码到Redis, 有效期5分钟
        redisUtil.setCode("email:code:" +sendCodeDTO.getUserEmail(), code,  5);
        log.info("验证码：{}", code);
        return Result.success();
    }

    private String generateVerificationCode(int length) {
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = (int) (Math.random() * chars.length());
            code.append(chars.charAt(index));
        }
        return code.toString();
   }

    /**
     * 新增接口：获取文章历史访客记录（默认返回当天）
     * @param id 文章ID
     * @param date 日期（yyyyMMdd格式，可选）
     * @return 包含访客IP列表和总访问次数
     */
    @GetMapping("/article/visitors/{id}")
    @ApiOperation(value = "获取文章访客记录（支持历史查询）")
    public Result<VisitorVO> getArticleVisitors(
            @PathVariable Long id,
            @RequestParam(required = false) String date) {

        if (date == null || date.isEmpty()) {
            date = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        }

        String ipKey = "article:visitor:ip:" + id + ":" + date;
        String countKey = "article:visit:count:" + id + ":" + date;

        return Result.success(VisitorVO.builder()
                .articleId(id)
                .visitorIps(redisUtil.getVisitorIps(ipKey))
                .totalVisits(redisUtil.getVisitCount(countKey))
                .build());
    }

    // 记录访客IP
    private void recordVisitorIp(Long articleId) {
        String today = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        String ipKey = "article:visitor:ip:" + articleId + ":" + today;
        String countKey = "article:visit:count:" + articleId;

        String clientIp = getClientIp();
        log.info("访客记录 - 文章ID: {}, IP: {}", articleId, clientIp);

        // 存储IP（自动去重）
        redisUtil.addIp(ipKey, clientIp);

        // 设置3天过期时间
        redisUtil.setExpiration(ipKey, 60 * 60 * 24 * 7);

        // 访问次数自增
        redisUtil.increment(countKey);

        // 设置永不过期
        redisUtil.persist(countKey);
    }



    private String getClientIp() {
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    if (attributes != null) {
        HttpServletRequest request = attributes.getRequest();

        String xForwardedFor = request.getHeader("X-Forwarded-For");
        String remoteAddr = request.getRemoteAddr();

        log.debug("Nginx转发信息 - X-Forwarded-For: {}, Real IP: {}",
                 xForwardedFor, remoteAddr);

        // 优先使用X-Forwarded-For
        if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            int index = xForwardedFor.indexOf(',');
            return (index > 0) ? xForwardedFor.substring(0, index).trim() : xForwardedFor;
        }

        // 回退到RemoteAddr
        if ("0:0:0:0:0:0:0:1".equals(remoteAddr)) {
            return "127.0.0.1";
        }

        return remoteAddr;
    }
    return "unknown";
}

}
